home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / emulator / uae-0.000 / uae-0 / uae-0.6.0 / xwin.c < prev   
C/C++ Source or Header  |  1996-05-26  |  21KB  |  804 lines

  1.  /* 
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * X interface
  5.   * 
  6.   * Copyright 1995, 1996 Bernd Schmidt
  7.   * Copyright 1996 Ed Hanway, Andre Beck, Samuel Devulder, Bruno Coste
  8.   */
  9.  
  10. #include "sysconfig.h"
  11. #include "sysdeps.h"
  12.  
  13. #include <X11/Xlib.h>
  14. #include <X11/Xutil.h>
  15. #include <X11/keysym.h>
  16. #include <X11/cursorfont.h>
  17.  
  18. #ifndef DONT_WANT_SHM
  19. #include <sys/ipc.h>
  20. #include <sys/shm.h>
  21. #include <X11/extensions/XShm.h>
  22. #endif
  23.  
  24. #include "config.h"
  25. #include "options.h"
  26. #include "memory.h"
  27. #include "custom.h"
  28. #include "newcpu.h"
  29. #include "xwin.h"
  30. #include "keyboard.h"
  31. #include "keybuf.h"
  32. #include "gui.h"
  33.  
  34. static Display *display;
  35. static int screen;
  36. static Window rootwin, mywin;
  37.  
  38. static GC whitegc,blackgc;
  39. static XColor black,white;
  40. static Colormap cmap;
  41.  
  42. static XImage *img;
  43. static Visual *vis;
  44. static XVisualInfo visualInfo;
  45. static int bitdepth;
  46. #ifndef DONT_WANT_SHM
  47. static XShmSegmentInfo shminfo;
  48. #endif
  49. static Cursor blankCursor, xhairCursor;
  50. static int cursorOn;
  51.  
  52. xcolnr xcolors[4096];
  53.  
  54.  /* Keyboard and mouse */
  55.  
  56. static int keystate[256];
  57.  
  58. int buttonstate[3];
  59. int lastmx, lastmy;
  60. int newmousecounters;
  61.  
  62. static int inwindow;
  63. const long int eventmask = (KeyPressMask|KeyReleaseMask|ButtonPressMask
  64.                 |ButtonReleaseMask|PointerMotionMask
  65.                 |FocusChangeMask|EnterWindowMask
  66.                 |ExposureMask
  67.                 |LeaveWindowMask);
  68.  
  69. static int vsize, hsize, hpixels;
  70. static char *oldpixbuf;
  71.  
  72. struct vidbuf_description gfxvidinfo;
  73.  
  74. void flush_line(int y)
  75. {
  76.     int xs = 0, xe = hsize - 1;
  77.     int len;
  78.     char *linebuf = y*gfxvidinfo.rowbytes + gfxvidinfo.bufmem;
  79.     
  80. #ifndef LOW_BANDWIDTH
  81.     fprintf(stderr, "Bug!\n");
  82. #endif
  83.     
  84.     switch(bitdepth) {
  85.      case 24: case 32:
  86.     {
  87.         int *newp = (int *)linebuf;
  88.         int *oldp = (int *)(oldpixbuf + y*gfxvidinfo.rowbytes);
  89.         while (newp[xs] == oldp[xs]) {
  90.         if (xs == xe)
  91.             return;
  92.         xs++;
  93.         }
  94.         while (newp[xe] == oldp[xe]) xe--;
  95.  
  96.         memcpy (oldp + xs, newp + xs, 4 * (xe - xs + 1));                       
  97.     }
  98.     break;
  99.      case 16: case 12:
  100.     {
  101.         short *newp = (short *)linebuf;
  102.         short *oldp = (short *)(oldpixbuf + y*gfxvidinfo.rowbytes);
  103.         while (newp[xs] == oldp[xs]) {
  104.         if (xs == xe)
  105.             return;
  106.         xs++;
  107.         }
  108.         while (newp[xe] == oldp[xe]) xe--;
  109.  
  110.         memcpy (oldp + xs, newp + xs, 2 * (xe - xs + 1));
  111.     }
  112.     break;
  113.      case 8:
  114.     {
  115.         char *newp = (char *)linebuf;
  116.         char *oldp = (char *)(oldpixbuf + y*gfxvidinfo.rowbytes);
  117.         while (newp[xs] == oldp[xs]) {
  118.         if (xs == xe)
  119.             return;
  120.         xs++;
  121.         }
  122.         while (newp[xe] == oldp[xe]) xe--;
  123.  
  124.         memcpy (oldp + xs, newp + xs, 1 * (xe - xs + 1));
  125.     }
  126.     break;
  127.     }
  128.  
  129.     len = xe - xs + 1;
  130.     
  131. #ifdef DONT_WANT_SHM
  132.     XPutImage(display, mywin, blackgc, img, xs, y, xs, y, len, 1);
  133. #else
  134.     XShmPutImage(display, mywin, blackgc, img, xs, y, xs, y, len, 1, 0);
  135. #endif
  136. }
  137.  
  138. void flush_block (int ystart, int ystop)
  139. {
  140.     int len, xs;
  141.     if (use_lores) {
  142.     len = 320;
  143.     xs = prev_max_diwstop - 328;
  144.     } else {
  145.     len = hpixels;
  146.     xs = 0;
  147.     }
  148. #ifdef DONT_WANT_SHM
  149.     XPutImage(display, mywin, blackgc, img, xs, ystart, 0, ystart, len, 
  150.           ystop - ystart + 1);
  151. #else
  152.     XShmPutImage(display, mywin, blackgc, img, xs, ystart, 0, ystart, len,
  153.          ystop - ystart + 1, 0);
  154. #endif
  155. }
  156.  
  157. void flush_screen (int ystart, int ystop)
  158. {
  159. #ifndef DONT_WANT_SHM
  160.     XSync(display, 0);
  161. #endif
  162. }
  163.  
  164. #ifndef DONT_WANT_SHM
  165. static void initShm(int depth)
  166. {
  167.     img = XShmCreateImage(display, vis, depth,
  168.               ZPixmap, 0, &shminfo, hsize, vsize);
  169.     
  170.     shminfo.shmid = shmget(IPC_PRIVATE, vsize * img->bytes_per_line,
  171.                IPC_CREAT | 0777);
  172.     shminfo.shmaddr = img->data = (char *)shmat(shminfo.shmid, 0, 0);
  173.     shminfo.readOnly = False;
  174.     /* let the xserver attach */
  175.     XShmAttach(display, &shminfo);
  176.     /* NOW ! */
  177.     XSync(display,0);
  178.     /* now deleting means making it temporary */
  179.     shmctl(shminfo.shmid, IPC_RMID, 0);
  180.     
  181.     gfxvidinfo.bufmem = img->data;
  182.     gfxvidinfo.rowbytes = img->bytes_per_line;
  183. }
  184. #endif
  185.  
  186. static __inline__ int bitsInMask(unsigned long mask)
  187. {
  188.     /* count bits in mask */
  189.     int n = 0;
  190.     while(mask) {
  191.     n += mask&1;
  192.     mask >>= 1;
  193.     }
  194.     return n;
  195. }
  196.  
  197. static __inline__ int maskShift(unsigned long mask)
  198. {
  199.     /* determine how far mask is shifted */
  200.     int n = 0;
  201.     while(!(mask&1)) {
  202.     n++;
  203.     mask >>= 1;
  204.     }
  205.     return n;
  206. }
  207.  
  208. static int get_color(int r, int g, int b, xcolnr *cnp)
  209. {
  210.     XColor col;
  211.     char str[10];
  212.     sprintf(str, "rgb:%x/%x/%x", r, g, b);
  213.     XParseColor(display, cmap, str, &col);
  214.     if (XAllocColor(display, cmap, &col)) {
  215.     *cnp = col.pixel;
  216.     return 1;
  217.     }
  218.     return 0;
  219. }
  220.  
  221. static int init_colors(void)
  222. {
  223.     if (visualInfo.depth != 8 && visualInfo.depth != 12 
  224.     && visualInfo.depth != 16 && visualInfo.depth != 24) {
  225.         fprintf(stderr, "Unsupported bit depth (%d)\n", visualInfo.depth);
  226.     return 0;
  227.     }
  228.     
  229. #ifdef __cplusplus
  230.     switch(visualInfo.c_class) 
  231. #else
  232.     switch(visualInfo.class) 
  233. #endif
  234.     {
  235.      case TrueColor: 
  236.     {        
  237.         int red_bits = bitsInMask(visualInfo.red_mask);
  238.         int green_bits = bitsInMask(visualInfo.green_mask);
  239.         int blue_bits = bitsInMask(visualInfo.blue_mask);
  240.         int red_shift = maskShift(visualInfo.red_mask);
  241.         int green_shift = maskShift(visualInfo.green_mask);
  242.         int blue_shift = maskShift(visualInfo.blue_mask);
  243.         alloc_colors64k(red_bits, green_bits, blue_bits, red_shift, 
  244.                 green_shift, blue_shift);
  245.     }
  246.     break;
  247.  
  248.      case GrayScale:
  249.      case PseudoColor:
  250.     alloc_colors256(get_color);
  251.     break;
  252.     
  253.      default:
  254. #ifdef __cplusplus
  255.     fprintf(stderr, "Unsupported visual class (%d)\n", visualInfo.c_class);
  256. #else
  257.     fprintf(stderr, "Unsupported visual class (%d)\n", visualInfo.class);
  258. #endif
  259.     return 0;
  260.     }
  261.     return 1;
  262. }
  263.  
  264. int graphics_init(void)
  265. {
  266.     int i;
  267.     char *display_name = 0;
  268.     XSetWindowAttributes wattr;
  269.  
  270.     if (screen_res < 3) {
  271. #ifdef LOW_BANDWIDTH
  272.     fprintf(stderr, "Low resolution mode not supported with LOW_BANDWIDTH.\n");
  273.     return 0;
  274. #else
  275.     fprintf(stderr, "Low resolution mode selected. Forcing 320x300.\n");
  276. #endif
  277.     }
  278.     
  279.     display = XOpenDisplay(display_name);
  280.     if (display == 0)  {
  281.     fprintf(stderr, "Can't connect to X server %s\n", XDisplayName(display_name));
  282.     return 0;
  283.     }
  284.     screen = XDefaultScreen(display);
  285.     rootwin = XRootWindow(display,screen);
  286.     
  287.     /* try for a 12 bit visual first, then a 16 bit, then a 24 bit, then 8 bit */
  288.     if (XMatchVisualInfo(display, screen, 12, TrueColor, &visualInfo)) {
  289.     } else if (XMatchVisualInfo(display, screen, 16, TrueColor, &visualInfo)) {
  290.     } else if (XMatchVisualInfo(display, screen, 24, TrueColor, &visualInfo)) {
  291.     } else if (XMatchVisualInfo(display, screen, 8, PseudoColor, &visualInfo)) {
  292.     /* for our HP boxes */
  293.     } else if (XMatchVisualInfo(display, screen, 8, GrayScale, &visualInfo)) {
  294.     } else {
  295.     fprintf(stderr, "Can't obtain appropriate X visual\n");
  296.     return 0;
  297.     }
  298.  
  299.     vis = visualInfo.visual;
  300.     bitdepth = visualInfo.depth;
  301.  
  302.     gfxvidinfo.pixbytes = (bitdepth == 24 || bitdepth == 32 ? 4
  303.                : bitdepth == 12 || bitdepth == 16 ? 2
  304.                : 1);
  305.     vsize = dont_want_aspect ? numscrlines : 2*numscrlines;
  306.     hsize = use_lores ? 400 : 800;
  307.     hpixels = use_lores ? 320 : 796;
  308.     fprintf(stderr, "Using %d bit visual\n", bitdepth);
  309.  
  310.     cmap = XCreateColormap(display, rootwin, vis, AllocNone);
  311.     XParseColor(display, cmap, "#000000", &black);
  312.     if (!XAllocColor(display, cmap, &black))
  313.     fprintf(stderr, "Whoops??\n");
  314.     XParseColor(display, cmap, "#ffffff", &white);
  315.     if (!XAllocColor(display, cmap, &white))
  316.     fprintf(stderr, "Whoops??\n");
  317.  
  318.     wattr.event_mask = eventmask;
  319.     wattr.background_pixel = black.pixel;
  320.     wattr.backing_store = Always;
  321.     wattr.backing_planes = bitdepth;
  322.     wattr.border_pixmap = None;
  323.     wattr.border_pixel = black.pixel;
  324.     wattr.colormap = cmap;
  325.  
  326.     mywin = XCreateWindow(display, rootwin, 0, 0, hpixels, vsize, 0,
  327.               bitdepth, InputOutput, vis,
  328.               CWEventMask|CWBackPixel|CWBorderPixel|CWBackingStore
  329.               |CWBackingPlanes|CWColormap,
  330.               &wattr);
  331.     XMapWindow(display,mywin);
  332.     XStoreName(display, mywin, "UAE");
  333.     
  334.     blankCursor = XCreatePixmapCursor(display,
  335.                       XCreatePixmap(display, mywin, 1, 1, 1),
  336.                       XCreatePixmap(display, mywin, 1, 1, 1), 
  337.                       &black, &white, 0, 0);
  338.     xhairCursor = XCreateFontCursor(display, XC_crosshair);
  339.  
  340.     whitegc = XCreateGC(display,mywin,0,0);
  341.     blackgc = XCreateGC(display,mywin,0,0);
  342.     
  343.     XSetForeground(display,blackgc,black.pixel);
  344.     XSetForeground(display,whitegc,white.pixel);
  345.  
  346. #ifdef DONT_WANT_SHM
  347.     gfxvidinfo.rowbytes = hsize * gfxvidinfo.pixbytes;
  348.     gfxvidinfo.bufmem = (char *)malloc(gfxvidinfo.rowbytes * vsize);
  349.     img = XCreateImage(display, vis, bitdepth, ZPixmap, 0, gfxvidinfo.bufmem, 
  350.                hsize, vsize, 32, 0);
  351. #else
  352.     initShm (bitdepth);
  353. #endif
  354. #ifdef LOW_BANDWIDTH
  355.     gfxvidinfo.maxblocklines = 0;
  356.     oldpixbuf = (char *)malloc(gfxvidinfo.rowbytes * vsize);
  357. #else
  358.     gfxvidinfo.maxblocklines = 100; /* whatever... */
  359. #endif
  360.  
  361.     if (!init_colors())
  362.     return 0;
  363.     
  364.     buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
  365.     for(i=0; i<256; i++)
  366.     keystate[i] = 0;
  367.     
  368.     lastmx = lastmy = 0; 
  369.     newmousecounters = 0;
  370.     inwindow = 0;
  371.     
  372.     if (use_xhair)
  373.     XDefineCursor(display, mywin, xhairCursor);
  374.     else
  375.     XDefineCursor(display, mywin, blankCursor);
  376.     cursorOn = 1;
  377.     return 1;
  378. }
  379.  
  380. void graphics_leave(void)
  381. {
  382.     XAutoRepeatOn(display);
  383. }
  384.  
  385. /* Decode KeySyms. This function knows about all keys that are common 
  386.  * between different keyboard languages. */
  387. static int kc_decode (KeySym ks)
  388. {
  389.     switch (ks) {    
  390.      case XK_B: case XK_b: return AK_B;
  391.      case XK_C: case XK_c: return AK_C;
  392.      case XK_D: case XK_d: return AK_D;
  393.      case XK_E: case XK_e: return AK_E;
  394.      case XK_F: case XK_f: return AK_F;
  395.      case XK_G: case XK_g: return AK_G;
  396.      case XK_H: case XK_h: return AK_H;
  397.      case XK_I: case XK_i: return AK_I;
  398.      case XK_J: case XK_j: return AK_J;
  399.      case XK_K: case XK_k: return AK_K;
  400.      case XK_L: case XK_l: return AK_L;
  401.      case XK_N: case XK_n: return AK_N;
  402.      case XK_O: case XK_o: return AK_O;
  403.      case XK_P: case XK_p: return AK_P;
  404.      case XK_R: case XK_r: return AK_R;
  405.      case XK_S: case XK_s: return AK_S;
  406.      case XK_T: case XK_t: return AK_T;
  407.      case XK_U: case XK_u: return AK_U;
  408.      case XK_V: case XK_v: return AK_V;
  409.      case XK_W: case XK_w: return AK_W;
  410.      case XK_X: case XK_x: return AK_X;
  411.     
  412.      case XK_0: return AK_0;
  413.      case XK_1: return AK_1;
  414.      case XK_2: return AK_2;
  415.      case XK_3: return AK_3;
  416.      case XK_4: return AK_4;
  417.      case XK_5: return AK_5;
  418.      case XK_6: return AK_6;
  419.      case XK_7: return AK_7;
  420.      case XK_8: return AK_8;
  421.      case XK_9: return AK_9;
  422.     
  423.     /* You never know which Keysyms might be missing on some workstation
  424.      * This #ifdef should be enough. */
  425. #if defined(XK_KP_Prior) && defined(XK_KP_Left) && defined(XK_KP_Insert) && defined (XK_KP_End)
  426.      case XK_KP_0: case XK_KP_Insert: return AK_NP0;
  427.      case XK_KP_1: case XK_KP_End: return AK_NP1;
  428.      case XK_KP_2: case XK_KP_Down: return AK_NP2;
  429.      case XK_KP_3: case XK_KP_Next: return AK_NP3;
  430.      case XK_KP_4: case XK_KP_Left: return AK_NP4;
  431.      case XK_KP_5: case XK_KP_Begin: return AK_NP5;
  432.      case XK_KP_6: case XK_KP_Right: return AK_NP6;
  433.      case XK_KP_7: case XK_KP_Home: return AK_NP7;
  434.      case XK_KP_8: case XK_KP_Up: return AK_NP8;
  435.      case XK_KP_9: case XK_KP_Prior: return AK_NP9;
  436. #else
  437.      case XK_KP_0: return AK_NP0;
  438.      case XK_KP_1: return AK_NP1;
  439.      case XK_KP_2: return AK_NP2;
  440.      case XK_KP_3: return AK_NP3;
  441.      case XK_KP_4: return AK_NP4;
  442.      case XK_KP_5: return AK_NP5;
  443.      case XK_KP_6: return AK_NP6;
  444.      case XK_KP_7: return AK_NP7;
  445.      case XK_KP_8: return AK_NP8;
  446.      case XK_KP_9: return AK_NP9;
  447. #endif
  448.      case XK_KP_Divide: return AK_NPDIV;
  449.      case XK_KP_Multiply: return AK_NPMUL;
  450.      case XK_KP_Subtract: return AK_NPSUB;
  451.      case XK_KP_Add: return AK_NPADD;
  452.      case XK_KP_Decimal: return AK_NPDEL;
  453.      case XK_KP_Enter: return AK_ENT;
  454.  
  455.      case XK_F1: return AK_F1;
  456.      case XK_F2: return AK_F2;
  457.      case XK_F3: return AK_F3;
  458.      case XK_F4: return AK_F4;
  459.      case XK_F5: return AK_F5;
  460.      case XK_F6: return AK_F6;
  461.      case XK_F7: return AK_F7;
  462.      case XK_F8: return AK_F8;
  463.      case XK_F9: return AK_F9;
  464.      case XK_F10: return AK_F10;
  465.         
  466.      case XK_BackSpace: return AK_BS;
  467.      case XK_Delete: return AK_DEL;
  468.      case XK_Control_L: case XK_Control_R: return AK_CTRL;
  469.      case XK_Tab: return AK_TAB;
  470.      case XK_Alt_L: return AK_LALT;
  471.      case XK_Alt_R: return AK_RALT;
  472.      case XK_Meta_R: case XK_Hyper_R: return AK_RAMI;
  473.      case XK_Meta_L: case XK_Hyper_L: return AK_LAMI;
  474.      case XK_Return: return AK_RET;
  475.      case XK_space: return AK_SPC;
  476.      case XK_Shift_L: return AK_LSH;
  477.      case XK_Shift_R: return AK_RSH;
  478.      case XK_Escape: return AK_ESC;
  479.  
  480.      case XK_Insert: return AK_BACKSLASH;
  481.      case XK_End: return AK_HELP;
  482.      case XK_Caps_Lock: return AK_CAPSLOCK;
  483.     
  484.      case XK_Up: return AK_UP;
  485.      case XK_Down: return AK_DN;
  486.      case XK_Left: return AK_LF;
  487.      case XK_Right: return AK_RT;
  488.     
  489.      case XK_F11: return AK_BACKSLASH;
  490.      case XK_F12: return AK_mousestuff;
  491. #ifdef XK_F14
  492.      case XK_F14:
  493. #endif
  494.      case XK_Scroll_Lock: return AK_inhibit;
  495.  
  496. #ifdef XK_Page_Up /* These are missing occasionally */
  497.      case XK_Page_Up: return AK_RAMI;          /* PgUp mapped to right amiga */
  498.      case XK_Page_Down: return AK_LAMI;        /* PgDn mapped to left amiga */
  499. #endif
  500.     }
  501.     return -1;
  502. }
  503.  
  504. static int decode_fr(KeySym ks)
  505. {
  506.     switch(ks) {        /* FR specific */
  507.      case XK_A: case XK_a: return AK_Q;
  508.      case XK_M: case XK_m: return AK_SEMICOLON; 
  509.      case XK_Q: case XK_q: return AK_A;    
  510.      case XK_Y: case XK_y: return AK_Y;
  511.      case XK_Z: case XK_z: return AK_Z;
  512.      case XK_bracketleft: return AK_LBRACKET;
  513.      case XK_bracketright: return AK_RBRACKET;
  514.      case XK_comma: return AK_M;
  515.      case XK_less: case XK_greater: return AK_LTGT;
  516.      case XK_period: return AK_COMMA;
  517.      case XK_parenright: return AK_MINUS;
  518.      case XK_equal: return AK_SLASH;
  519.      case XK_numbersign: return AK_NUMBERSIGN;
  520.      case XK_slash: return AK_PERIOD;
  521.      case XK_minus: return AK_EQUAL;
  522.      case XK_backslash: return AK_BACKSLASH;
  523.     }
  524.  
  525.     return -1;
  526. }
  527.  
  528. static int decode_us(KeySym ks)
  529. {
  530.     switch(ks) {    /* US specific */    
  531.      case XK_A: case XK_a: return AK_A;
  532.      case XK_M: case XK_m: return AK_M;
  533.      case XK_Q: case XK_q: return AK_Q;
  534.      case XK_Y: case XK_y: return AK_Y;
  535.      case XK_Z: case XK_z: return AK_Z;
  536.      case XK_bracketleft: return AK_LBRACKET;
  537.      case XK_bracketright: return AK_RBRACKET;
  538.      case XK_comma: return AK_COMMA;
  539.      case XK_period: return AK_PERIOD;
  540.      case XK_slash: return AK_SLASH;
  541.      case XK_semicolon: return AK_SEMICOLON;
  542.      case XK_minus: return AK_MINUS;
  543.      case XK_equal: return AK_EQUAL;
  544.     /* this doesn't work: */
  545.      case XK_quoteright: return AK_QUOTE;
  546.      case XK_quoteleft: return AK_BACKQUOTE;
  547.      case XK_backslash: return AK_NUMBERSIGN;
  548.     }
  549.  
  550.     return -1;
  551. }
  552.  
  553. static int decode_de(KeySym ks)
  554. {
  555.     switch(ks) {
  556.     /* DE specific */
  557.      case XK_A: case XK_a: return AK_A;
  558.      case XK_M: case XK_m: return AK_M;
  559.      case XK_Q: case XK_q: return AK_Q;
  560.      case XK_Y: case XK_y: return AK_Z;
  561.      case XK_Z: case XK_z: return AK_Y;
  562.      case XK_Odiaeresis: case XK_odiaeresis: return AK_SEMICOLON;
  563.      case XK_Adiaeresis: case XK_adiaeresis: return AK_QUOTE;
  564.      case XK_Udiaeresis: case XK_udiaeresis: return AK_LBRACKET;
  565.      case XK_plus: case XK_asterisk: return AK_RBRACKET;
  566.      case XK_comma: return AK_COMMA;
  567.      case XK_period: return AK_PERIOD;
  568.      case XK_less: case XK_greater: return AK_LTGT;
  569.      case XK_numbersign: return AK_NUMBERSIGN;
  570.      case XK_ssharp: return AK_MINUS;
  571.      case XK_apostrophe: return AK_EQUAL;
  572.      case XK_asciicircum: return AK_BACKQUOTE;
  573.      case XK_minus: return AK_SLASH;
  574.     }
  575.  
  576.     return -1;
  577. }
  578.  
  579. static int decode_se(KeySym ks)
  580. {
  581.     switch(ks) {
  582.     /* SE specific */
  583.      case XK_A: case XK_a: return AK_A;
  584.      case XK_M: case XK_m: return AK_M;
  585.      case XK_Q: case XK_q: return AK_Q;
  586.      case XK_Y: case XK_y: return AK_Y;
  587.      case XK_Z: case XK_z: return AK_Z;
  588.      case XK_Odiaeresis: case XK_odiaeresis: return AK_SEMICOLON;
  589.      case XK_Adiaeresis: case XK_adiaeresis: return AK_QUOTE;
  590.      case XK_Aring: case XK_aring: return AK_LBRACKET;
  591.      case XK_comma: return AK_COMMA;
  592.      case XK_period: return AK_PERIOD;
  593.      case XK_minus: return AK_SLASH;
  594.      case XK_less: case XK_greater: return AK_LTGT;
  595.      case XK_plus: case XK_question: return AK_EQUAL;
  596.      case XK_at: case XK_onehalf: return AK_BACKQUOTE;
  597.      case XK_asciitilde: case XK_asciicircum: return AK_RBRACKET;
  598.      case XK_backslash: case XK_bar: return AK_MINUS;
  599.     
  600.      case XK_numbersign: return AK_NUMBERSIGN;
  601.     }
  602.  
  603.     return -1;
  604.  }
  605.  
  606. static int decode_it(KeySym ks)
  607. {
  608.     switch(ks) {
  609.     /* IT specific */
  610.      case XK_A: case XK_a: return AK_A;
  611.      case XK_M: case XK_m: return AK_M;
  612.      case XK_Q: case XK_q: return AK_Q;
  613.      case XK_Y: case XK_y: return AK_Y;
  614.      case XK_Z: case XK_z: return AK_Z;
  615.      case XK_Ograve: case XK_ograve: return AK_SEMICOLON;
  616.      case XK_Agrave: case XK_agrave: return AK_QUOTE;
  617.      case XK_Egrave: case XK_egrave: return AK_LBRACKET;
  618.      case XK_plus: case XK_asterisk: return AK_RBRACKET;
  619.      case XK_comma: return AK_COMMA;
  620.      case XK_period: return AK_PERIOD;
  621.      case XK_less: case XK_greater: return AK_LTGT;
  622.      case XK_backslash: case XK_bar: return AK_BACKQUOTE;               
  623.      case XK_apostrophe: return AK_MINUS;           
  624.      case XK_Igrave: case XK_igrave: return AK_EQUAL;
  625.      case XK_minus: return AK_SLASH;
  626.      case XK_numbersign: return AK_NUMBERSIGN;
  627.     }
  628.  
  629.     return -1;
  630. }
  631.  
  632. static int keycode2amiga(XKeyEvent *event)
  633. {
  634.     KeySym ks;
  635.     int as;
  636.     int index = 0;
  637.     
  638.     do {
  639.     ks = XLookupKeysym(event, index);
  640.     as = kc_decode (ks);
  641.     
  642.     if (as == -1) {        
  643.         switch(keyboard_lang) {
  644.  
  645.         case KBD_LANG_FR:
  646.         as = decode_fr(ks);
  647.         break;
  648.  
  649.          case KBD_LANG_US:
  650.         as = decode_us(ks);
  651.         break;
  652.         
  653.          case KBD_LANG_DE:
  654.         as = decode_de(ks);
  655.         break;
  656.         
  657.          case KBD_LANG_SE:
  658.         as = decode_se(ks);
  659.         break;
  660.         
  661.          case KBD_LANG_IT:
  662.         as = decode_it(ks);
  663.         break;
  664.  
  665.          default:
  666.         as = -1;
  667.         break;
  668.         }
  669.     }
  670.     if(-1 != as)
  671.         return as;
  672.     index++;
  673.     } while (ks != NoSymbol);
  674.     return -1;
  675. }
  676.  
  677. static struct timeval lastMotionTime;
  678.  
  679. void handle_events(void)
  680. {
  681.     int repeat, refresh = 0;
  682.     newmousecounters = 0;
  683.     gui_handle_events();
  684.     
  685.     do {
  686.     XEvent event;
  687.     if (!XCheckMaskEvent(display, eventmask, &event)) break;
  688.     repeat = 0;
  689.     
  690.     switch(event.type) {
  691.      case KeyPress: {        
  692.          int kc = keycode2amiga((XKeyEvent *)&event);
  693.          if (kc == -1) break;
  694.          switch (kc) {
  695.           case AK_mousestuff:
  696.          togglemouse();
  697.          break;
  698.  
  699.           case AK_inhibit:
  700.          inhibit_frame ^= 1;
  701.          break;
  702.  
  703.           default:
  704.               if (!keystate[kc]) {
  705.              keystate[kc] = 1;
  706.              record_key (kc << 1);
  707.          }
  708.          break;
  709.          }
  710.          break;
  711.      }
  712.      case KeyRelease: {         
  713.          int kc = keycode2amiga((XKeyEvent *)&event);
  714.          if (kc == -1) break;
  715.          keystate[kc] = 0;
  716.          record_key ((kc << 1) | 1);
  717.          break;
  718.      }
  719.      case ButtonPress:
  720.         buttonstate[((XButtonEvent *)&event)->button-1] = 1;
  721.         break;
  722.      case ButtonRelease:
  723.         buttonstate[((XButtonEvent *)&event)->button-1] = 0;
  724.         break;
  725.      case EnterNotify:
  726.         newmousecounters = 1;
  727.         lastmx = ((XCrossingEvent *)&event)->x;
  728.         lastmy = ((XCrossingEvent *)&event)->y;
  729.         repeat = 1;
  730.         inwindow = 1;
  731.         break;
  732.      case LeaveNotify:
  733.         inwindow = 0;
  734.         repeat = 1;
  735.         break;
  736.      case FocusIn:
  737.         XAutoRepeatOff(display);
  738.         repeat = 1;
  739.         break;
  740.      case FocusOut:
  741.         XAutoRepeatOn(display);
  742.         repeat = 1;
  743.         break;
  744.      case MotionNotify:
  745.         if (inwindow) {        
  746.         lastmx = ((XMotionEvent *)&event)->x;
  747.         lastmy = ((XMotionEvent *)&event)->y;
  748.         if(!cursorOn && use_xhair) {
  749.             XDefineCursor(display, mywin, xhairCursor);
  750.             cursorOn = 1;
  751.         }
  752.         gettimeofday(&lastMotionTime, NULL);
  753.         }
  754.         repeat = 1;
  755.         break;
  756.      case Expose:
  757.         refresh = 1;
  758.         repeat  = 1;
  759.         break;
  760.     }
  761.     } while (repeat);
  762.  
  763. #ifdef DONT_WANT_SHM
  764.     if(refresh) 
  765.     XPutImage(display, mywin, blackgc, img, 0, 0, 0, 0, hpixels, vsize);
  766. #else
  767.     if(refresh)
  768.     XShmPutImage(display, mywin, blackgc, img, 0, 0, 0, 0, hpixels, vsize, 0);
  769. #endif
  770.     if(cursorOn && use_xhair) {
  771.     struct timeval now;
  772.     int diff;
  773.     gettimeofday(&now, NULL);
  774.     diff = (now.tv_sec - lastMotionTime.tv_sec) * 1000000 + 
  775.         (now.tv_usec - lastMotionTime.tv_usec);
  776.     if(diff > 1000000) {
  777.         XDefineCursor(display, mywin, blankCursor);
  778.         cursorOn = 0;
  779.     }
  780.     }
  781.     
  782.     /* "Affengriff" */
  783.     if(keystate[AK_CTRL] && keystate[AK_LAMI] && keystate[AK_RAMI])
  784.         MC68000_reset();
  785. }
  786.  
  787. int debuggable(void)
  788. {
  789.     return 1;
  790. }
  791.  
  792. int needmousehack(void)
  793. {
  794.     return 1;
  795. }
  796.  
  797. void LED(int on)
  798. {
  799.     XKeyboardControl control;
  800.     control.led = 1; /* implementation defined */
  801.     control.led_mode = on ? LedModeOn : LedModeOff;
  802.     XChangeKeyboardControl(display, KBLed | KBLedMode, &control);
  803. }
  804.